﻿using MongoDB.Bson;
using Naruto.FileStorage.Helper;
using Naruto.FileStorage.Object;
using Naruto.FileStorage.Provider.MongoDB.Interface;
using Naruto.FileStorage.Provider.MongoDB.Object;
using Naruto.MongoDB.Interface;
using System;
using System.Collections.Generic;
using System.IO;
using System.Text;
using System.Threading.Tasks;

namespace Naruto.FileStorage.Provider.MongoDB.Internal
{
    public class MongoDBFile : IMongoDBFile
    {
        private readonly IMongoRepository<MongoDBFileStorageContext> mongoRepository;

        //private const string BuckName
        public MongoDBFile(IMongoRepository<MongoDBFileStorageContext> _mongoRepository)
        {
            mongoRepository = _mongoRepository;
        }

        /// <summary>
        /// 添加文件
        /// </summary>
        /// <param name="file">文件流</param>
        /// <param name="fileNameSplit">存储的文件名</param>
        /// <param name="fileStream">是否为大文件 >15M </param>
        /// <returns>返回文件请求路径</returns>
        public async Task<string> AddFileAsync(Stream fileStream, bool isBigFile, FileNameSplit fileNameSplit)
        {
            //参数验证
            if (fileNameSplit == null || fileStream == null || fileStream.Length <= 0 || !fileStream.CanRead)
            {
                return default;
            }
            //获取字节数
            var bytes = new byte[fileStream.Length];
            await fileStream.ReadAsync(bytes);
            //验证是否为大文件
            if (!isBigFile)
            {
                await mongoRepository.Command<UploadFileModel>().AddAsync(fileNameSplit.DirectoryName, new UploadFileModel
                {
                    FileName = fileNameSplit.FileName,
                    FileBytes = bytes,
                    CreateTime = DateTime.Now
                });
            }
            else
            {
                var gridFs = mongoRepository.GridFS();
                //更改存放的目录地址
                await gridFs.ChangeBucketNameAsync(fileNameSplit.DirectoryName);
                //上传
                await gridFs.UploadFromBytesAsync(fileNameSplit.FileName, bytes);
            }
            var requestPath = $"{(isBigFile ? MongoDBFileTypeEnum.BIG.ToString().ToLower() : MongoDBFileTypeEnum.SMALL.ToString().ToLower())}{fileNameSplit}";
            return requestPath;
        }

        public async Task DeleteFileAsync(bool isBigFile, FileNameSplit fileNameSplit)
        {
            if (!isBigFile)
            {
                await mongoRepository.Command<UploadFileModel>().DeleteAsync(fileNameSplit.DirectoryName, a => a.FileName == fileNameSplit.FileName);
            }
            else
            {
                var gridFs = mongoRepository.GridFS();
                //更改存放的目录地址
                await gridFs.ChangeBucketNameAsync(fileNameSplit.DirectoryName);
                //获取文件的信息
                var fileList = await gridFs.FindByNameAsync(fileNameSplit.FileName);
                if (fileList == null)
                    return;
                //删除所有名称相同的文件
                foreach (var item in fileList)
                {
                    await gridFs.DeleteByIdAsync(item.Id);
                }
            }
        }

        public async Task<byte[]> GetFileAsync(bool isBigFile, FileNameSplit fileNameSplit)
        {
            if (!isBigFile)
            {
                //获取信息
                var fileModel = await mongoRepository.Query<UploadFileModel>().FirstOrDefaultAsync(fileNameSplit.DirectoryName, a => a.FileName == fileNameSplit.FileName);
                if (fileModel == null)
                {
                    return default;
                }
                return fileModel.FileBytes;
            }
            else
            {
                var gridFs = mongoRepository.GridFS();
                //更改存放的目录地址
                await gridFs.ChangeBucketNameAsync(fileNameSplit.DirectoryName);
                //验证文件是否存在
                if (!(await gridFs.ExistsByNameAsync(fileNameSplit.FileName)))
                    return default;
                //获取流文件
                var stream = await gridFs.GetDownloadStreamByNameAsync(fileNameSplit.FileName);
                if (stream == null)
                {
                    return default;
                }
                using (stream.Stream)
                {
                    var bytes = new byte[stream.GridFSFile.Length];
                    await stream.Stream.ReadAsync(bytes);
                    return bytes;
                }
            }
        }
    }
}
